package com.talent.web.redis;

import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Service;

import java.time.Duration;
import java.util.List;

/**
 * @ClassName：RedisLockService
 * @Author: hszhou
 * @Date: 2025/1/22 11:33
 * @Description: 必须描述类做什么事情, 实现什么功能
 */
@Service
public class RedisLockService {


    private static final Long DEFAULT_LOCK_EXPIRE_TIME=60L;


    private final StringRedisTemplate stringRedisTemplate;


    public RedisLockService(StringRedisTemplate stringRedisTemplate){
        this.stringRedisTemplate = stringRedisTemplate;
    }

    public Boolean tryLock(String key, String value, Duration timeout){
        long waitMills = timeout.toMillis();
        long currentTimeMillis = System.currentTimeMillis();
        do {
            boolean lock = lock(key, value, DEFAULT_LOCK_EXPIRE_TIME);
            if(lock){
                return true;
            }

        }while (System.currentTimeMillis()<currentTimeMillis+waitMills);
        return false;
    }

    public boolean lock(String key,String value,Long exprie){
        String luaScript="if redis.call('setnx',KEYS[1],ARGV[1])==1 then return redis.call('expire',KEYS[1],ARGV[2]) else return 0 end";
        DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>(luaScript, Long.class);
        Long result = stringRedisTemplate.execute(redisScript,  List.of(key),String.valueOf(value));
        assert result != null;
        return result.equals(1L);
    }

    public boolean releaseLock(String key,String value){
        String luaScript="if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
        DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>(luaScript, Long.class);

       ;
        Long result = stringRedisTemplate.execute(redisScript, List.of(key),String.valueOf(value));
        assert result != null;
        return result.equals(1L);

    }
}
